﻿// -----------------------------------------------------------------------
// <copyright file="Exception.cs" company="Company">
// Company 2011
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using Company.IO.Interfaces;

namespace Company.System.IO
{
    /// <summary>
    /// The exception that is thrown when an error occurr
    /// </summary>
    [Guid("5e9fe473-76dd-431a-a720-2fa7a6061e22")]
    [Serializable]
    public class Exception : IException
    {
        /// <summary>
        /// Initializes a new instance of the Exception class
        /// </summary>
        /// <param name="systemIoConverter">The converter to use</param>
        /// <param name="exception">The Exception object</param>
        public Exception(ISystemIoConverter systemIoConverter, global::System.Exception exception)
        {
            SystemIoConverter = systemIoConverter;
            InternalException = exception;
        }

        /// <summary>
        /// Get or set the internal exception
        /// </summary>
        protected global::System.Exception InternalException { get; set; }

        /// <summary>
        /// Get or set the internal converter
        /// </summary>
        protected ISystemIoConverter SystemIoConverter { get; set; }

        #region IException Members

        /// <summary>
        /// Gets a collection of key/value pairs that provide additional user-defined information about the exception.
        /// </summary>
        IDictionary IException.Data
        {
            get { return InternalException.Data; }
        }

        /// <summary>
        /// Gets a message that describes the current exception.
        /// </summary>
        string IException.Message
        {
            get { return InternalException.Message; }
        }

        /// <summary>
        /// Gets the Exception instance that caused the current exception.
        /// </summary>
        IException IException.InnerException
        {
            get { return Convert(InternalException.InnerException); }
        }

        /// <summary>
        /// Gets the method that throws the current exception.
        /// </summary>
        MethodBase IException.TargetSite
        {
            get { return InternalException.TargetSite; }
        }

        /// <summary>
        /// Gets a string representation of the immediate frames on the call stack.
        /// </summary>
        string IException.StackTrace
        {
            get { return InternalException.StackTrace; }
        }

        /// <summary>
        /// Gets or sets a link to the help file associated with this exception.
        /// </summary>
        string IException.HelpLink
        {
            get { return InternalException.HelpLink; }

            set { InternalException.HelpLink = value; }
        }

        /// <summary>
        /// Gets or sets the name of the application or the object that causes the error.
        /// </summary>
        string IException.Source
        {
            get { return InternalException.Source; }

            set { InternalException.Source = value; }
        }

        /// <summary>
        /// Gets or sets HRESULT, a coded numerical value that is assigned to a specific exception.
        /// </summary>
        int IException.HRESULT
        {
            get { throw new NotImplementedException(); }

            set { throw new NotImplementedException(); }
        }

        /// <summary>
        /// When overridden in a derived class, returns the Exception that is the root cause of one or more subsequent exceptions.
        /// </summary>
        /// <returns>
        /// The first exception thrown in a chain of exceptions.
        /// If the InnerException property of the current exception is a null reference (Nothing in Visual Basic),
        /// this property returns the current exception.
        /// </returns>
        IException IException.GetBaseException()
        {
            return Convert(InternalException.GetBaseException());
        }

        /// <summary>
        /// Returns a <see cref="T:System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> that represents this instance.
        /// </returns>
        string IException.ToString()
        {
            return InternalException.ToString();
        }

        /// <summary>
        /// Gets the <see cref="T:System.Type"/> of the current instance.
        /// </summary>
        /// <returns>
        /// The <see cref="T:System.Type"/> instance that represents the exact runtime type of the current instance.
        /// </returns>
        Type IException.GetType()
        {
            return InternalException.GetType();
        }

        /// <summary>
        /// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the target object.
        /// </summary>
        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data.</param>
        /// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization.</param>
        /// <exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            InternalException.GetObjectData(info, context);
        }

        #endregion

        /// <summary>
        /// Converts the specified exception.
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <returns>The converted object</returns>
        private IException Convert(global::System.Exception exception)
        {
            return SystemIoConverter.Convert(exception);
        }
    }
}